<template>
  <Dialog
    :visible="visible"
    @update:visible="$emit('update:visible', $event)"
    modal
    :style="{ width: '95vw', height: '95vh' }"
    :closable="true"
    :draggable="false"
    :resizable="true"
    class="bpmn-designer-dialog"
  >
    <template #header>
      <div class="dialog-header">
        <h3>BPMN流程设计器</h3>
        <div class="dialog-actions">
          <Button
            icon="pi pi-save"
            label="保存"
            size="small"
            @click="saveDiagram"
            :disabled="!isModelerReady"
          />
          <Button
            icon="pi pi-download"
            label="导出XML"
            size="small"
            @click="exportXml"
            :disabled="!isModelerReady"
          />
          <Button
            icon="pi pi-times"
            label="关闭"
            size="small"
            severity="secondary"
            @click="$emit('update:visible', false)"
          />
        </div>
      </div>
    </template>

    <div class="designer-container">
      <!-- 左侧画布区域 -->
      <div class="canvas-area">
        <div ref="bpmnContainer" class="bpmn-canvas"></div>
        <div v-if="!isModelerReady" class="loading-overlay">
          <i class="pi pi-spin pi-spinner" style="font-size: 2rem;"></i>
          <p>正在加载BPMN设计器...</p>
          <Button
            label="重新初始化"
            size="small"
            severity="secondary"
            @click="retryInit"
            style="margin-top: 16px;"
          />
        </div>
      </div>

      <!-- 右侧属性面板 -->
      <div class="properties-panel-area">
        <div class="properties-panel-header">
          <h4>属性面板</h4>
          <Button
            icon="pi pi-times"
            size="small"
            text
            @click="closePropertiesPanel"
            v-if="selectedElement"
          />
        </div>
        <div ref="propertiesContainer" class="properties-panel-content">
          <div v-if="!selectedElement" class="no-selection">
            <i class="pi pi-info-circle" style="font-size: 2rem; color: #6c757d;"></i>
            <p>请选择一个元素来编辑其属性</p>
          </div>
        </div>
      </div>
    </div>
  </Dialog>
</template>

<script setup lang="ts">
import { ref, watch, onUnmounted, nextTick } from 'vue'
import Dialog from 'primevue/dialog'
import Button from 'primevue/button'
import BpmnModeler from 'bpmn-js/lib/Modeler'
// @ts-ignore
import { BpmnPropertiesPanelModule } from 'bpmn-js-properties-panel'
// @ts-ignore
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda'

interface Props {
  visible: boolean
  initialXml?: string
}

interface Emits {
  (e: 'update:visible', value: boolean): void
  (e: 'save', xml: string): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

// 响应式数据
const bpmnContainer = ref<HTMLElement | null>(null)
const isModelerReady = ref(false)
let modeler: any = null
const selectedElement = ref<any>(null)
const propertiesContainer = ref<HTMLElement | null>(null)

// 完全空白的BPMN XML - 只包含基本的定义结构
const emptyBpmnXml = `<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn">
  <bpmn:process id="Process_1" isExecutable="true">
  </bpmn:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>`

// 设置元素选择监听
const setupElementSelection = () => {
  console.log('设置元素选择监听...')
  
  const eventBus = modeler.get('eventBus')
  
  // 监听元素选择事件
  eventBus.on('selection.changed', (event: any) => {
    const selection = event.newSelection
    if (selection && selection.length > 0) {
      const element = selection[0]
      selectedElement.value = element
      console.log('选中元素:', element.id, element.type)
      
      // 更新属性面板
      updatePropertiesPanel(element)
    } else {
      selectedElement.value = null
      console.log('取消选择元素')
    }
  })

  // 监听元素点击事件
  eventBus.on('element.click', (event: any) => {
    const element = event.element
    if (element && element.id !== '__implicitroot') {
      selectedElement.value = element
      console.log('点击元素:', element.id, element.type)
      
      // 更新属性面板
      updatePropertiesPanel(element)
    }
  })
  
  console.log('元素选择监听已设置')
}

// 更新属性面板
const updatePropertiesPanel = (element: any) => {
  if (!modeler || !propertiesContainer.value) {
    return
  }

  try {
    const propertiesPanel = modeler.get('propertiesPanel')
    if (propertiesPanel) {
      console.log('属性面板对象:', propertiesPanel)
      
      // 清空现有内容
      if (propertiesContainer.value) {
        propertiesContainer.value.innerHTML = ''
      }
      
      // 将属性面板附加到容器
      propertiesPanel.attachTo(propertiesContainer.value)
      
      // 尝试不同的方法来打开属性面板
      if (typeof propertiesPanel.open === 'function') {
        propertiesPanel.open(element)
        console.log('使用open方法打开属性面板')
      } else if (typeof propertiesPanel.show === 'function') {
        propertiesPanel.show(element)
        console.log('使用show方法打开属性面板')
      } else if (typeof propertiesPanel.render === 'function') {
        propertiesPanel.render(element)
        console.log('使用render方法打开属性面板')
      } else {
        // 尝试直接设置选中元素
        const selection = modeler.get('selection')
        if (selection) {
          selection.select(element)
          console.log('通过selection选择元素')
        }
      }
      
      console.log('属性面板已更新:', element.id)
    }
  } catch (error: any) {
    console.error('更新属性面板失败:', error)
  }
}

// 关闭属性面板
const closePropertiesPanel = () => {
  selectedElement.value = null
  if (propertiesContainer.value) {
    propertiesContainer.value.innerHTML = ''
  }
  console.log('属性面板已关闭')
}

// 初始化BPMN Modeler
const initModeler = async () => {
  if (!bpmnContainer.value || !propertiesContainer.value) {
    console.error('容器未准备好')
    return
  }

  const container = bpmnContainer.value
  
  // 检查容器尺寸
  if (container.offsetWidth === 0 || container.offsetHeight === 0) {
    console.error('容器尺寸为0，延迟初始化')
    setTimeout(() => {
      initModeler()
    }, 100)
    return
  }
  
  console.log('容器尺寸:', container.offsetWidth, 'x', container.offsetHeight)
  
  // 临时抑制已弃用API的警告
  const originalWarn = console.warn
  console.warn = function(...args) {
    const message = args.join(' ')
    if (message.includes('ContextPad#getPad is deprecated')) {
      return // 忽略这个特定的警告
    }
    originalWarn.apply(console, args)
  }
  
  // 创建BPMN Modeler实例
  console.log('开始创建BPMN Modeler...')
  console.log('BpmnPropertiesPanelModule:', BpmnPropertiesPanelModule)
  console.log('camundaModdleDescriptor:', camundaModdleDescriptor)
  
  modeler = new BpmnModeler({
    container: container,
    additionalModules: [
      BpmnPropertiesPanelModule
    ],
    moddleExtensions: {
      camunda: camundaModdleDescriptor
    },
    propertiesPanel: {
      parent: propertiesContainer.value
    }
  })
  
  console.log('BPMN Modeler创建完成')
  
  // 检查属性面板是否正确初始化
  try {
    const propertiesPanel = modeler.get('propertiesPanel')
    console.log('属性面板初始化检查:', propertiesPanel)
    if (propertiesPanel) {
      console.log('属性面板可用方法:', Object.getOwnPropertyNames(propertiesPanel))
    }
  } catch (error: any) {
    console.error('属性面板初始化检查失败:', error)
  }
  
  // 恢复原始的console.warn
  console.warn = originalWarn
  
  console.log('BPMN Modeler实例创建成功')
  
  // 导入BPMN XML
  const xmlToImport = props.initialXml || emptyBpmnXml
  
  try {
    await modeler.importXML(xmlToImport)
    console.log('BPMN XML导入成功')
  } catch (error: any) {
    console.error('BPMN XML导入失败:', error)
    // 如果导入失败，尝试导入默认XML
    try {
      await modeler.importXML(emptyBpmnXml)
      console.log('默认BPMN XML导入成功')
    } catch (defaultError: any) {
      console.error('默认BPMN XML导入也失败:', defaultError)
    }
  }
  
  // 获取画布并居中显示
  const canvas = modeler.get('canvas')
  canvas.zoom('fit-viewport')
  console.log('画布缩放设置完成')
  
  // 设置元素选择监听
  setupElementSelection()
  
  isModelerReady.value = true
}

// 重试初始化
const retryInit = () => {
  console.log('重试初始化BPMN设计器...')
  isModelerReady.value = false
  if (modeler) {
    try {
      modeler.destroy()
    } catch (error: any) {
      console.warn('销毁现有modeler失败:', error)
    }
    modeler = null
  }
  
  nextTick(() => {
    setTimeout(() => {
      initModeler()
    }, 100)
  })
}

// 保存图表
const saveDiagram = async () => {
  if (!modeler) {
    console.error('Modeler未初始化')
    return
  }

  try {
    const result = await modeler.saveXML({ format: true })
    console.log('保存成功:', result.xml)
    emit('save', result.xml)
  } catch (error: any) {
    console.error('保存失败:', error)
  }
}

// 导出XML
const exportXml = async () => {
  if (!modeler) {
    console.error('Modeler未初始化')
    return
  }

  try {
    const result = await modeler.saveXML({ format: true })
    console.log('导出XML成功:', result.xml)
    
    // 创建下载链接
    const blob = new Blob([result.xml], { type: 'application/xml' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = 'process.bpmn'
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)
  } catch (error: any) {
    console.error('导出XML失败:', error)
  }
}

// 监听visible变化
watch(() => props.visible, (newVisible) => {
  if (newVisible) {
    nextTick(() => {
      setTimeout(() => {
        initModeler()
      }, 100)
    })
  } else {
    // 清理资源
    if (modeler) {
      try {
        modeler.destroy()
      } catch (error: any) {
        console.warn('销毁modeler失败:', error)
      }
      modeler = null
    }
    isModelerReady.value = false
    selectedElement.value = null
  }
})

// 组件卸载时清理
onUnmounted(() => {
  if (modeler) {
    try {
      modeler.destroy()
    } catch (error: any) {
      console.warn('组件卸载时销毁modeler失败:', error)
    }
  }
})
</script>

<style scoped>
@import 'bpmn-js/dist/assets/diagram-js.css';
@import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
@import '@bpmn-io/properties-panel/dist/assets/properties-panel.css';

.dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
}

.dialog-header h3 {
  margin: 0;
  font-size: 1.2rem;
  font-weight: 600;
}

.dialog-actions {
  display: flex;
  gap: 8px;
}

.designer-container {
  flex: 1;
  position: relative;
  display: flex;
  flex-direction: row;
  overflow: hidden;
  background: #f5f5f5;
  height: calc(95vh - 120px);
}

.canvas-area {
  flex: 1;
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.bpmn-canvas {
  width: 100%;
  height: 100%;
  background: white;
}

.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.9);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.loading-overlay p {
  margin: 16px 0 0 0;
  color: #666;
  font-size: 14px;
}

.properties-panel-area {
  width: 350px;
  background: white;
  border-left: 1px solid #e0e0e0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.properties-panel-header {
  padding: 16px;
  border-bottom: 1px solid #e0e0e0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: #f8f9fa;
}

.properties-panel-header h4 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: #333;
}

.properties-panel-content {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
}

.no-selection {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
  color: #6c757d;
}

.no-selection p {
  margin: 16px 0 0 0;
  font-size: 14px;
}

/* 确保BPMN设计器样式正确 */
:deep(.djs-palette) {
  background: white;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
}

:deep(.djs-palette .entry) {
  width: 30px;
  height: 30px;
  margin: 2px;
  border-radius: 4px;
  transition: all 0.2s ease;
}

:deep(.djs-palette .entry:hover) {
  background: #f0f0f0;
  transform: scale(1.1);
}

:deep(.bpp-properties-panel) {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

:deep(.bpp-properties-panel .bpp-group-header) {
  background: #f8f9fa;
  border-bottom: 1px solid #e0e0e0;
  padding: 8px 12px;
  font-weight: 600;
  color: #333;
}

:deep(.bpp-properties-panel .bpp-field) {
  margin-bottom: 12px;
}

:deep(.bpp-properties-panel .bpp-field label) {
  display: block;
  margin-bottom: 4px;
  font-weight: 500;
  color: #555;
  font-size: 13px;
}

:deep(.bpp-properties-panel input, .bpp-properties-panel select, .bpp-properties-panel textarea) {
  width: 100%;
  padding: 6px 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 13px;
  transition: border-color 0.2s ease;
}

:deep(.bpp-properties-panel input:focus, .bpp-properties-panel select:focus, .bpp-properties-panel textarea:focus) {
  outline: none;
  border-color: #007bff;
  box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
}

:deep(.bpp-properties-panel .bpp-button) {
  background: #007bff;
  color: white;
  border: none;
  padding: 6px 12px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
  transition: background-color 0.2s ease;
}

:deep(.bpp-properties-panel .bpp-button:hover) {
  background: #0056b3;
}
</style>